#ifndef MYAMG_CSRSMOOTHER_CUH
#define MYAMG_CSRSMOOTHER_CUH
#include <../Data/CSRMatrix.cuh>
#include <CSRSmootherKernels.cuh>

namespace myamg {
    template<typename Integer, typename Real, typename Allocator, typename Derived>
    class CSRSmoother {
    public:
        using matrixType = CSRMatrix<Integer, Real, Allocator>;
        using vectorType = Vector<Real, Allocator>;
        using integerType = Integer;
        using realType = Real;
        using allocatorType = Allocator;

        void setup(const matrixType &A, const bool reuse = false) {
            static_cast<Derived *>(this)->setupImpl(A, reuse);
        }

        void pre(const matrixType &A, const vectorType &b, vectorType &x, const int step,
                 const bool x0Zero = false) {
            static_cast<Derived *>(this)->preImpl(A, b, x, step, x0Zero);
        }

        void preResid(const matrixType &A, const vectorType &b, vectorType &x, vectorType &r,
                      const int step, const bool x0Zero = false) {
            static_cast<Derived *>(this)->preResidImpl(A, b, x, r, step, x0Zero);
        }

        void post(const matrixType &A, const vectorType &b, vectorType &x, const int step) {
            static_cast<Derived *>(this)->postImpl(A, b, x, step);
        }

        void apply(const matrixType &A, const vectorType &b, vectorType &x, const int step,
                   const bool x0Zero = false) {
            static_cast<Derived *>(this)->applyImpl(A, b, x, step, x0Zero);
        }
    };
}

#endif //MYAMG_CSRSMOOTHER_CUH
